package com.koalacloud.koala.zhaikucloud.util;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import lombok.Data;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

/**
 * @Author: GuoYang
 * @Description
 * @create 2022-05-16
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.elasticsearch")
public class ElasticSearchClientConfig {
    /**
     * 多个IP逗号隔开
     */
    private String hosts;
    private String username;
    private String password;
    private String crtPath;

    @Bean
    public ElasticsearchClient elasticsearchClient() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {
        HttpHost[] httpHosts = toHttpHost();
//        es设置可以http访问方式
//        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
//        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
//
////        RestClient client = RestClient.builder(httpHosts).build();
//        RestClient client = RestClient.builder(new HttpHost("localhost", 9200))
//            .setHttpClientConfigCallback(HttpClientBuilder -> HttpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)).build();
//
//        ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper());
//        return new ElasticsearchClient(transport);

//        es设置https访问 根据用户名、密码方式连接
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials(username, password));

//        Path caCertificatePath = Paths.get("/Users/liuxg/test/elasticsearch-8.1.2/config/certs/http_ca.crt");
        Path caCertificatePath = Paths.get(crtPath);
        CertificateFactory factory =
                CertificateFactory.getInstance("X.509");
        Certificate trustedCa;
        try (InputStream is = Files.newInputStream(caCertificatePath)) {
            trustedCa = factory.generateCertificate(is);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        KeyStore trustStore = KeyStore.getInstance("pkcs12");
        trustStore.load(null, null);
        trustStore.setCertificateEntry("ca", trustedCa);
        SSLContextBuilder sslContextBuilder = SSLContexts.custom()
                .loadTrustMaterial(trustStore, null);
        final SSLContext sslContext = sslContextBuilder.build();

//        RestClientBuilder builder = RestClient.builder(
//                        new HttpHost("localhost", 9200, "https"))
        RestClientBuilder builder = RestClient.builder(httpHosts)
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(
                            HttpAsyncClientBuilder httpClientBuilder) {
                        return httpClientBuilder.setSSLContext(sslContext)
                                .setDefaultCredentialsProvider(credentialsProvider);  // API key需要注释改行
                    }
                });

        // API key 方式
//        Header[] defaultHeaders =
//                new Header[]{new BasicHeader("Authorization",
//                        "ApiKey eTNFMUZZRUJ2dF96NXB6TUk1Ylk6NFFYSlJmTVBUeXV6clktYTh3N0k2dw==")};
//        builder.setDefaultHeaders(defaultHeaders);

        RestClient restClient = builder.build();

        // Create the transport with a Jackson mapper
        ElasticsearchTransport transport = new RestClientTransport(
                restClient, new JacksonJsonpMapper());

//        client = new ElasticsearchClient(transport);
//        asyncClient = new ElasticsearchAsyncClient(transport);
        return new ElasticsearchClient(transport);
    }

//    @Bean
//    public RestClient restClient() {
//        HttpHost[] httpHosts = toHttpHost();
//
//        RestClient restClient = RestClient.builder(httpHosts).build();
//
//        return restClient;
//    }


    /**
     * 解析hosts
     * @return
     */
    private HttpHost[] toHttpHost() {
        if (!StringUtils.hasLength(hosts)) {
            throw new RuntimeException("elasticsearch.hosts不能为空！");
        }
        String[] hostArray = hosts.split(",");
        HttpHost[] httpHosts = new HttpHost[hostArray.length];
        HttpHost httpHost;
        for (int i = 0; i < hostArray.length; i++) {
            String[] strings = hostArray[i].split(":");
            httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "https");
            httpHosts[i] = httpHost;
        }

        return httpHosts;
    }

}
